package com.example.smartpark.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * JWT工具类
 * 用于生成、解析和验证JWT令牌
 */
@Slf4j
public class JwtUtils {

    /**
     * 密钥（实际项目中应当使用更复杂的密钥并从配置中读取）
     */
    private static final String SECRET_KEY = "smartpark_jwt_secret_key";

    /**
     * 过期时间，默认为24小时（单位：毫秒）
     */
    private static final long EXPIRATION_TIME = 24 * 60 * 60 * 1000; // 24小时

    /**
     * 生成JWT令牌
     *
     * @param userId 用户ID
     * @return JWT令牌
     */
    public static String generateToken(Integer userId) {
        return generateToken(userId, EXPIRATION_TIME);
    }

    /**
     * 生成JWT令牌
     *
     * @param userId       用户ID
     * @param expireMillis 过期时间（毫秒）
     * @return JWT令牌
     */
    public static String generateToken(Integer userId, long expireMillis) {
        // 签发时间
        Date now = new Date();
        // 过期时间
        Date expireDate = new Date(now.getTime() + expireMillis);

        // 添加payload信息
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId", userId);

        // 生成令牌
        return Jwts.builder()
                .setClaims(claims)              // 设置payload
                .setIssuedAt(now)               // 设置签发时间
                .setExpiration(expireDate)      // 设置过期时间
                .signWith(SignatureAlgorithm.HS256, SECRET_KEY) // 设置签名算法和密钥
                .compact();                     // 生成JWT字符串
    }

    /**
     * 从JWT令牌中获取用户ID
     *
     * @param token JWT令牌
     * @return 用户ID
     */
    public static Integer getUserIdFromToken(String token) {
        Claims claims = getClaimsFromToken(token);
        return claims != null ? claims.get("userId", Integer.class) : null;
    }

    /**
     * 验证JWT令牌是否有效
     *
     * @param token JWT令牌
     * @return 是否有效
     */
    public static boolean validateToken(String token) {
        try {
            // 解析令牌，如果解析成功且未过期，则令牌有效
            Claims claims = getClaimsFromToken(token);
            return claims != null && !isTokenExpired(claims);
        } catch (Exception e) {
            // 解析失败，令牌无效
            log.error("JWT令牌验证失败：", e);
            return false;
        }
    }

    /**
     * 从令牌中获取Claims
     *
     * @param token JWT令牌
     * @return Claims对象
     */
    private static Claims getClaimsFromToken(String token) {
        try {
            return Jwts.parser()
                    .setSigningKey(SECRET_KEY)
                    .parseClaimsJws(token)
                    .getBody();
        } catch (ExpiredJwtException e) {
            // 令牌已过期，返回过期的Claims
            return e.getClaims();
        } catch (Exception e) {
            // 令牌解析失败
            log.error("JWT令牌解析失败：", e);
            return null;
        }
    }

    /**
     * 判断令牌是否过期
     *
     * @param claims Claims对象
     * @return 是否过期
     */
    private static boolean isTokenExpired(Claims claims) {
        Date expiration = claims.getExpiration();
        return expiration != null && expiration.before(new Date());
    }
} 